home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-09 | 6.4 KB | 265 lines | [TEXT/KEEN] |
- #$Whazzat: undeclarate (translate to English) most C declarations.
- #Typically run this on one declaration at a time by
- #selecting the declaration in the front text window and
- #running this on “Front text selection”. Output is to stdout.
- #If you run this on several declarations at once, each declaration
- #(except maybe the last) should be terminated with a semicolon.
- #Not for function/struct/union/enum definitions, and any comments
- #should start and end on the same line.
- #
- #See “whazzatTest” for some example declarations.
- # (You can run this program on all of whazzatTest at once)
- #
- #This is good enough to untangle a great many declarations,
- #but not good enough to verify that a declaration is correct.
- #
- #If called from within EnterAct with a project open (and a
- #dictionary built for the project), type specifications are
- #extended to all typedefs, structs, unions, and enums defined
- #in the source code for your project.
- #For example, if your project contains a definition of NODE,
- #then "NODE *" appearing in a declaration will be translated
- # to "pointer to NODE"; if you have no proect open or NODE
- #cannot be found in your project dictionary, then "NODE *"
- #will be translated to just "pointer to", type left unspecified.
-
- #For a (simpler) C version of this, see
- # "The C Programming Language" by Kernighan & Ritchie, pg 122
- # and "The C Answer Book" by Tondo & Gimpel, pg 140, 146
- # (both published by Prentice Hall)
-
- # User’s Manual references:
- # «hAWK User’s Manual» «F Running hAWK programs»
- # «hAWK User’s Manual» «L 5 Regular expressions»
- # «hAWK User’s Manual» «M 5 Built-in string and file functions»
- # «hAWK User’s Manual» «K 4 Built-in variables»
- # «hAWK User’s Manual» «K 8 Arrays»
- # «hAWK User’s Manual» «N User-defined functions»
- # «hAWK User’s Manual» «P 3 The getline function»
- # «hAWK User’s Manual» «O 3 Output into files»
- # «hAWK User’s Manual» «Q The hAWK function»
-
- BEGIN { if (ARGC != 2) # comment this out to allow multiple files (!?)
- {
- print "Whoa, just one little bit at a time please."
- exit
- }
- min_line_width = 60;
- #Some "enumerated" constants
- NAME = 1; PARENS = 2; BRACKETS = 3; DDD = 4;
- NO = 0; YES = 1; EOF = -1;
- #Some keywords, associatively arrayed:
- #specifiers
- types["char"] = 1
- types["int"] = 1
- types["void"] = 1
- types["long"] = 1
- types["float"] = 1
- types["double"] = 1
- types["short"] = 1
- types["..."] = 1
- #qualifiers
- typeq["const"] = 1
- typeq["volatile"] = 1
- typeq["unsigned"] = 1
- typeq["signed"] = 1
- typeq["struct"] = 1
- typeq["union"] = 1
- typeq["enum"] = 1
- typeq["pascal"] = 1
- typeq["Pascal"] = 1
-
- prevtoken = NO;
- Whazzat();
- }
-
- function Whazzat()
- {
- while (gettoken() != EOF)
- {
- if (token == "extern" || token == "static")
- {
- gettoken();
- }
- datatype = token
- while (typequal() == YES)
- {
- gettoken();
- datatype = datatype " " token
- }
- out = ""
- name = ""
- dcl();
- nicely_print_decl();
- }
- }
-
- function dcl( ns)
- {
- for (ns = 0; gettoken() == "*"; )
- ++ns;
- dirdcl();
- while (ns-- > 0)
- out = out " pointer to"
- }
-
- function dirdcl( type)
- {
-
- if (tokentype == "(")
- {
- dcl();
- if (tokentype != ")")
- errmsg("Error: missing )")
- }
- else if (tokentype == NAME)
- {
- if (name == "")
- name = token
- }
- else
- prevtoken = YES;
- while ((type = gettoken()) == PARENS ||
- type == BRACKETS || type == "(")
- {
- if (type == PARENS)
- out = out " function returning"
- else if (type == "(")
- {
- out = out " function expecting"
- parmdcl();
- out = out " and returning"
- }
- else
- {
- out = out " array" token " of"
- }
- }
- }
-
- function errmsg(msg)
- {
- prevtoken = YES
- print msg
- }
-
- function parmdcl()
- {
- do
- {
- dclspec();
- } while (tokentype == ",");
- if (tokentype != ")")
- errmsg("missing ) in parameter declaration");
- }
-
- function dclspec( temp)
- {
- gettoken();
- do
- {
- if (tokentype != NAME && tokentype != DDD)
- {
- prevtoken = YES
- dcl();
- }
- else if (typespec() == YES || typequal() == YES)
- {
- temp = temp " " token
- gettoken();
- }
- else #ignore it - typically a name for a parameter eg (int x, int y,...)
- gettoken();# or errmsg("unknown type in parameter list");
- } while (tokentype != "," && tokentype != ")");
- out = out temp
- if (tokentype == ",")
- out = out ","
- }
-
- function typespec( type)
- {
- if (token in types)
- return YES;
- else if ((type = lookup(token)) == 16 || # typedef
- type == 32 || type == 64 || # struct, union tag
- type == 128) # enum tag
- return YES;
- return NO;
- }
-
- function typequal()
- {
- if (token in typeq)
- return YES;
- return NO;
- }
-
- #Read in a line at a time, and trim tokens from
- #beginning of line. A bit wasteful, but time is not
- #critical. Type of token is returned, and placed in tokentype;
- #the token string is placed in token. Note no “ungetch()” is
- #required, because the matches go just the right distance.
- function gettoken()
- {
- if (tokentype == EOF)
- return EOF;
- if (prevtoken == YES)
- {
- prevtoken = NO
- return tokentype;
- }
- #Get next line if needed
- while (length(line) == 0)
- {
- if (getline line <= 0)
- return tokentype = EOF;
- sub(/^[ \t]+/, "", line) #null out blank line - rarely needed
- sub(/^\/\*.*\*\//, "", line) #kill one-line comment
- }
- #remove leading white space and comments on one line
- sub(/^[ \t]+/, "", line)
- sub(/^\/\*.*\*\//, "", line)
-
- if ((match(line, /^\(\)/) && (tokentype = PARENS)) || # ()
- (match(line, /^\(/) && (tokentype = "(")) || # ( etc
- (match(line, /^\[([^\]])*\]/) && (tokentype = BRACKETS)) || # [...]
- (match(line, /^\.\.\./) && (tokentype = DDD)) || #variable args ...
- (match(line, /^[A-Za-z_][A-Za-z0-9_]*/) && (tokentype = NAME))) # a C word
- {
- token = substr(line, 1, RLENGTH)
- line = substr(line, RLENGTH + 1)
- return tokentype
- }
- else
- {
- tokentype = substr(line,1,1)
- line = substr(line, 2)
- return tokentype
- }
- }
-
- function nicely_print_decl( total_decl, one_line, tabber, i, len)
- {
- #print name ":", out, datatype -- works, but may produce long line
- #min_line_width determines rough width of long lines
- total_decl = name ": " out " " datatype;
- tabber = ""
- while ((len = length(total_decl)) > min_line_width)
- {
- i = min_line_width
- #Round up to nearest word end.
- while (i <= len && substr(total_decl, i, 1) ~ /[A-Za-z0-9_]/)
- ++i;
- one_line = substr(total_decl, 1, i)
- print tabber one_line
- #Skip trailing space.
- while (i <= len && substr(total_decl, i, 1) ~ /[^A-Za-z0-9_]/)
- ++i;
- total_decl = substr(total_decl, i)
- if (tabber == "")
- tabber = "\t"
- }
- if (total_decl != "")
- print tabber total_decl;
- }
-